package com.tencent.wepay.service.pay;

import org.apache.commons.beanutils.BeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tencent.wepay.WepayManager;
import com.tencent.wepay.constant.enums.TradeTypeEnum;
import com.tencent.wepay.handler.xml.XStreamHandler;
import com.tencent.wepay.listener.Listener;
import com.tencent.wepay.protocol.http.HttpsRequest;
import com.tencent.wepay.protocol.pay.domain.Refund;
import com.tencent.wepay.protocol.pay.request.RefundInfoRequest;
import com.tencent.wepay.protocol.pay.request.RefundRequest;
import com.tencent.wepay.protocol.pay.response.RefundInfoResponse;
import com.tencent.wepay.protocol.pay.response.RefundResponse;
import com.tencent.wepay.spi.WepayRepository;

public class RefundService {
	private final static String url="https://api.mch.weixin.qq.com/secapi/pay/refund";
	private final static String queryUrl="https://api.mch.weixin.qq.com/pay/refundquery";
	private static Logger logger=LoggerFactory.getLogger(RefundService.class);
	public static RefundResponse refund(Refund refund){
		WepayRepository repository=null;
		if(TradeTypeEnum.JSAPI.equals(refund.getTradeType())){
			repository=WepayManager.getJsapiRepository();
		}
		else if(TradeTypeEnum.APP.equals(refund.getTradeType())){
			repository=WepayManager.getAppRepository();
		}
		RefundRequest request=new RefundRequest();
		request.setAppid(repository.getAppid());
		request.setKey(repository.getKey());
		request.setMchId(repository.getMchId());
		try {
			BeanUtils.copyProperties(request, refund);
			if(request.validation()){
				String result=HttpsRequest.getInstance().post(url,request.toXML(),repository);
				RefundResponse response=XStreamHandler.toBean(RefundResponse.class,result);
				return response;
			}
		} catch (Exception e) {
			logger.error("send request error", e);
		}
		return null;
	}
	public static RefundResponse refund(Refund refund,Listener<RefundRequest, RefundResponse> listner){
		WepayRepository repository=null;
		if(TradeTypeEnum.JSAPI.equals(refund.getTradeType())){
			repository=WepayManager.getJsapiRepository();
		}
		else if(TradeTypeEnum.APP.equals(refund.getTradeType())){
			repository=WepayManager.getAppRepository();
		}
		RefundRequest request=new RefundRequest();
		request.setAppid(repository.getAppid());
		request.setKey(repository.getKey());
		request.setMchId(repository.getMchId());
		request.setOpUserId(repository.getMchId());
		try {
			BeanUtils.copyProperties(request, refund);
			if(listner!=null)
				listner.beforeSend(request);
			if(request.validation()){
				String result=HttpsRequest.getInstance().post(url,request.toXML(),repository);
				RefundResponse response=XStreamHandler.toBean(RefundResponse.class,result);
				if ("SUCCESS".equalsIgnoreCase(response.getReturnCode())
						&& "SUCCESS".equalsIgnoreCase(response.getResultCode())) {
					if(listner!=null)
						listner.onSuccess(response);
				}
				else{
					if(listner!=null)
						listner.onFail(response);
				}
				return response;
			}
		} catch (Exception e) {
			logger.error("send request error", e);
			if(listner!=null)
				listner.onError(e);
		}
		return null;
	}
	public static RefundInfoResponse queryByTradeNo(String tradeNo,TradeTypeEnum tradeType){
		WepayRepository repository=null;
		if(TradeTypeEnum.JSAPI.equals(tradeType)){
			repository=WepayManager.getJsapiRepository();
		}
		else if(TradeTypeEnum.APP.equals(tradeType)){
			repository=WepayManager.getAppRepository();
		}
		RefundInfoRequest request=new RefundInfoRequest();
		request.setAppid(repository.getAppid());
		request.setKey(repository.getKey());
		request.setMchId(repository.getMchId());
		request.setTradeNo(tradeNo);
		try {
			if(request.validation()){
				String result=HttpsRequest.getInstance().post(queryUrl,request.toXML(),repository);
				RefundInfoResponse response=XStreamHandler.toBean(RefundInfoResponse.class,result);
				return response;
			}
		} catch (Exception e) {
			logger.error("send request error", e);
		}
		return null;
	}
	public static RefundInfoResponse queryByTransId(String transactionId,TradeTypeEnum tradeType){
		WepayRepository repository=null;
		if(TradeTypeEnum.JSAPI.equals(tradeType)){
			repository=WepayManager.getJsapiRepository();
		}
		else if(TradeTypeEnum.APP.equals(tradeType)){
			repository=WepayManager.getAppRepository();
		}
		RefundInfoRequest request=new RefundInfoRequest();
		request.setAppid(repository.getAppid());
		request.setKey(repository.getKey());
		request.setMchId(repository.getMchId());
		request.setTransactionId(transactionId);;
		try {
			if(request.validation()){
				String result=HttpsRequest.getInstance().post(queryUrl,request.toXML(),repository);
				RefundInfoResponse response=XStreamHandler.toBean(RefundInfoResponse.class,result);
				return response;
			}
		} catch (Exception e) {
			logger.error("send request error", e);
		}
		return null;
	}
	public static RefundInfoResponse queryByOutRefundNo(String outRefundNo,TradeTypeEnum tradeType){
		WepayRepository repository=null;
		if(TradeTypeEnum.JSAPI.equals(tradeType)){
			repository=WepayManager.getJsapiRepository();
		}
		else if(TradeTypeEnum.APP.equals(tradeType)){
			repository=WepayManager.getAppRepository();
		}
		RefundInfoRequest request=new RefundInfoRequest();
		request.setAppid(repository.getAppid());
		request.setKey(repository.getKey());
		request.setMchId(repository.getMchId());
		request.setOutRefundNo(outRefundNo);;
		try {
			if(request.validation()){
				String result=HttpsRequest.getInstance().post(queryUrl,request.toXML(),repository);
				RefundInfoResponse response=XStreamHandler.toBean(RefundInfoResponse.class,result);
				return response;
			}
		} catch (Exception e) {
			logger.error("send request error", e);
		}
		return null;
	}
	public static RefundInfoResponse queryByRefundId(String refundId,TradeTypeEnum tradeType){
		WepayRepository repository=null;
		if(TradeTypeEnum.JSAPI.equals(tradeType)){
			repository=WepayManager.getJsapiRepository();
		}
		else if(TradeTypeEnum.APP.equals(tradeType)){
			repository=WepayManager.getAppRepository();
		}
		RefundInfoRequest request=new RefundInfoRequest();
		request.setAppid(repository.getAppid());
		request.setKey(repository.getKey());
		request.setMchId(repository.getMchId());
		request.setRefundId(refundId);
		try {
			if(request.validation()){
				String result=HttpsRequest.getInstance().post(queryUrl,request.toXML(),repository);
				RefundInfoResponse response=XStreamHandler.toBean(RefundInfoResponse.class,result);
				return response;
			}
		} catch (Exception e) {
			logger.error("send request error", e);
		}
		return null;
	}
}
